const { SerialPort } = require('serialport');

/* Initialization */

function comBasicInit (index) {
    /* get the com ports of system */
    SerialPort.list().then((ports) => {
        if (ports.length > 0) {
            ocom.config.doms.com.path.innerHTML = '';
        }
        ports.forEach((port) => {
            let dom = document.createElement('option');
            dom.value = port.path;
            dom.text = port.path;
            ocom.config.doms.com.path.appendChild(dom);
        });
    });

    /* open com by serial port */
    ocom.config.doms.configComBtn.onclick = function (e) {
        if (!ocom.com.isopen) {
            /* parameter check */
            let info = {};
            info.path = ocom.config.doms.com.path.value;
            if (info.path != 'null') {
                info.baudRate = Number(ocom.config.doms.com.baudRate.value);    // TODO: Custom it
                info.dataBits = Number(ocom.config.doms.com.dataBits.value);
                info.stopBits = Number(ocom.config.doms.com.stopBits.value);
                info.parity = ocom.config.doms.com.parity.value;
                info.flowControl = false;   // TODO: Add it to UI
                ocom.com.serialport = new SerialPort(info);
                /* the operation after `com opened` */
                ocom.com.serialport.on('open', () => {
                    ocom.com.isopen = true;
                    comOpenedAni();
                    infoPrint(info.path + " opened", true);
                });
                /* the operation after `com closed` */
                ocom.com.serialport.on('close', (err) => {
                    if (err) {
                        infoPrint(`${err}, Fatal Error, Port maybe out!`, false, 20);
                    } else {
                        infoPrint(info.path + " closed", false);
                    }
                    ocom.com.isopen = false;
                    comClosedAni();
                });
                /* the operation after `com error occured` */
                ocom.com.serialport.on('error', (err) => {
                    ocom.com.isopen = false;
                    infoPrint(`${err}`, false);
                });
                /* recevie data, NOTE: if you monitor the event of `port out`, you must set the
                   serialport listener `on('data')` */
                let recvTimer = null;
                let dataLine = [];
                ocom.com.serialport.on('data', (data) => {
                    /* clear the timer of the newline division, interrupt the newline operation */
                    if (recvTimer != null) {
                        clearTimeout(recvTimer);
                    }
                    dataLine = dataLine.concat(Array.from(data));   // NOTE: type(data) is Buffer not Array
                    /* create a timer, do the newline division operation after timeout */
                    recvTimer = setTimeout(() => {
                        consoleAutoR(ocom.console.doms.consoleMsgs, dataLine);
                        dataLine = [];

                        // /* deep copy */
                        // ocom.com.recvData = JSON.parse(JSON.stringify(dataLine));
                        // /* clear up `dataLine` for next newline data */
                        // dataLine = [];
                        // /* asynchronous invoke the message handle function */
                        // new Promise((resolve, reject) => {
                        //     resolve('hello');
                        // }).then((res) => {
                        //     console.log(res);
                        // });
                    }, ocom.com.dataDivTime);
                });
            }
        } else {
            /* Remedial works are in `serialport.on('close')` above */
            ocom.com.serialport.close();
        }
    }
}

function comWriteHex (hexStr) {
    if (ocom.com.isopen) {
        let arr = hexStr.split(' ').filter((ele) => {
            return ele && parseInt(ele, 16);    /* hex string to number */
        }).map((str) => {
            return parseInt(str, 16);
        });
        ocom.com.serialport.write(Buffer.from(arr), (err) => {
            if (err) {
                infoPrint(err, 0, 20);
            } else {
                infoPrint('Hex data has been sent');
            }
        });
    }
}

function comWriteStr (str) {
    ocom.com.serialport.write(str, (err) => {
        if (err) {
            infoPrint(err, 0, 20);
        } else {
            infoPrint('String data has been sent');
        }
    });
}
